`include "defines.d"
`define NOSYNTH
module arbiter_5x5(clock, reset, request, grant, priority_update_enable);



	// A 5x5 round-robin oblivious ripple arbiter	
	input wire clock, reset, priority_update_enable;
	input wire [4:0] request;
	output wire [4:0] grant;

	reg [4:0] priority, next_priority;
	wire [4:0] carry, sub_carry;
	
	initial begin
		priority = 5'b10000;
	end
	
	assign grant = request & (priority | carry);
	assign sub_carry = priority | carry;
	
	assign carry[0] = ~request[4] & sub_carry[4];
	assign carry[1] = ~request[0] & sub_carry[0];
	assign carry[2] = ~request[1] & sub_carry[1];
	assign carry[3] = ~request[2] & sub_carry[2];
	assign carry[4] = ~request[3] & sub_carry[3];
	
	always @(posedge clock or negedge reset) begin	
		if(!reset) priority <= 5'b00001;
		else priority <= next_priority;
	end

	// combinational loop
	always @ * begin
		if(!priority_update_enable)
			next_priority = priority;
		else begin
			case  (grant)
				5'b00000: begin
					next_priority = priority;	
				end
				5'b00001: begin
					next_priority = 5'b00010;
				end
				5'b00010: begin
					next_priority = 5'b00100;
				end
				5'b00100: begin
					next_priority = 5'b01000;
				end
				5'b01000: begin
					next_priority = 5'b10000;
					end
				5'b10000: begin
					next_priority = 5'b00001;
				end
				default: begin
				`ifdef NOSYNTH
						next_priority = 5'b00001;
				//	$display("EERROR! Grants are not zero-one-hot!\n");
				`endif			
				end
			endcase
		end
	end
endmodule



